package lucene;

import java.io.File;
import java.util.HashSet;
import java.util.Set;

import com.contexticon.model.Scene;
import com.contexticon.model.Transcript;
import com.contexticon.model.Utterance;
import com.contexticon.parser.OurParser;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericField;
import org.apache.lucene.index.FieldInfo.IndexOptions;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;

public class UtteranceDatabase {

	private IndexWriter writer;
	private QueryParser parser;
	private String myID;
	Directory dir;
	IndexSearcher searcher;

	public UtteranceDatabase(String utteranceIndexDirectory) {

		this.myID = utteranceIndexDirectory;
		try {
			System.out.println("Indexing to directory '"
					+ utteranceIndexDirectory + "'...");

			dir = new RAMDirectory();
			
			//Directory dir = FSDirectory.open(new File(utteranceIndexDirectory));
			
			// use empty stopword set instead of standard set for English
			// to include 'no' and 'in' etc. in the Demo Video
			Set stopWords = new HashSet();
			Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_31, stopWords);
			
			IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_31,
					analyzer);
			//searcher = new IndexSearcher(FSDirectory.open(new File(
			//		utteranceIndexDirectory)));

			// Create a new index in the directory, removing any
			// previously indexed documents:
			iwc.setOpenMode(OpenMode.CREATE);
			// Add new documents to an existing index:
			// iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);

			writer = new IndexWriter(dir, iwc);
			
			
		    parser = new QueryParser(Version.LUCENE_31, "contents", analyzer);
		} catch (Exception e) {

			System.out.println(e.toString());
		}

	}

	public void indexTranscrirpts(String[] transcriptPaths, String[] mediaPaths, String[] titles ) {

		
		// loop over transcripts
		for (int t=0; t<transcriptPaths.length; t++) {
			Transcript transcript = OurParser.readConfig(transcriptPaths[t]);
		
		// loop over scenes
		 for (Scene scene : transcript.sceneList) {
			 // loop over utterances in the scene
			 for (Utterance utterance : scene.utteranceList) {
				 utterance.setMovieId(t);
				 addUtterance(utterance);
				// add a row to the model
			 }// loop over utterances			 
		 } // end loop over scenes			 
		}// loop over files
		 
		close();
	}
	
	void addUtterance(Utterance u) {
		
		//System.out.println("Adding utterance: " + u.getUtterance());
	      try {

	          // make a new, empty document
	          Document doc = new Document();

	          // Add the contents of the file to a field named "contents".  Specify a Reader,
	          // so that the text of the file is tokenized and indexed, but not stored.
	          // Note that FileReader expects the file to be in UTF-8 encoding.
	          // If that's not the case searching for special characters will fail.
	          doc.add(new Field("contents", u.getText(), Field.Store.YES, Field.Index.ANALYZED));
	          
	          
	          NumericField starttimeField = new NumericField("starttime", Field.Store.YES, false);
	          Float startTime = u.getStartTime();
	          starttimeField.setFloatValue(startTime);
	          doc.add(starttimeField);

	          NumericField endtimeField = new NumericField("endtime", Field.Store.YES, false);
	          Float endTime = u.getEndTime();
	          endtimeField.setFloatValue(endTime);
	          doc.add(endtimeField);
	          
	          NumericField movieIdField = new NumericField("movieId", Field.Store.YES, false);
	          movieIdField.setIntValue(u.getMovieId());
	          doc.add(movieIdField);
	          
	         // New index, so we just add the document (no old document can be there):
	         writer.addDocument(doc);
	      }
	      catch (Exception e) {
	    	  System.out.println(e.toString());
	      }
		
	      
		
		
	}
	
	void close() {
		try {
		writer.optimize();
		writer.close();
		}
		catch (Exception e) {
			
		}
	}

	public Utterance[] search(String q) {


		Utterance[] resultArray = null;		
		
		try {
		writer.close();
		} catch(Exception e) {
			
		}
		
		
		try {
		if (null==searcher) {
		    IndexReader reader = IndexReader.open(dir);
		    searcher = new IndexSearcher(reader);
			
			//searcher = new IndexSearcher(FSDirectory.open(new File(this.myID)));
		}
		}
		catch (Exception e) {
			System.out.println(e.toString());
		}
		
		System.out.println(q);
		Query query;
		try {
			query = parser.parse(q);
			
		    TopDocs results = searcher.search(query, 10000);
		    ScoreDoc[] hits = results.scoreDocs;
		    int numTotalHits = results.totalHits;
		    System.out.println(numTotalHits + " total matching documents");
		    
		    resultArray= new Utterance[numTotalHits];
		    
		    for (int i = 0; i < numTotalHits; i++) {
		    	
		        Document doc = searcher.doc(hits[i].doc);
		        String subtitle = doc.get("contents");
		        System.out.println(doc.getFields().toString());
		        String start =  doc.get("starttime");
		        String end = doc.get("endtime");
		        String movieId = doc.get("movieId");
		        
		        //System.out.println(subtitle);
		        System.out.println(subtitle + " " + start + " " + end);
		       
		        Utterance anUtterance = new Utterance();
		        anUtterance.setText(subtitle);
		        anUtterance.setStartTime(Float.parseFloat(start));
		        anUtterance.setEndTime(Float.parseFloat(end));
		        anUtterance.setMovieId(Integer.parseInt(movieId));
		        
		        resultArray[i] = anUtterance;
		        
		        
            }
		    
		    
		} catch (Exception e) {
			System.out.println(e.toString());
		}
	    

		return resultArray;
	}

}
